﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;

namespace Devonline.Identity.Admin.Controllers;

/// <summary>
/// 资源管理
/// </summary>    
[Route("api/[controller]")]
[ApiController]
[SecurityHeaders]
[Authorize(Roles = GROUP_MAINTAINERS)]
public class ResourcesController : ODataModelServiceController<Resource, ResourceViewModel>
{
    private readonly IExcelExportService _excelExportService;
    private readonly ResourceAccessStore _resourceAccessStore;
    private static CancellationToken CancellationToken => CancellationToken.None;

    public ResourcesController(
        ILogger<ResourcesController> logger,
        IDataWithAttachmentService<Resource> dataService,
        IExcelExportService excelExportService,
        ResourceAccessStore resourceAccessStore
        ) : base(logger, dataService) => (_excelExportService, _resourceAccessStore) = (excelExportService, resourceAccessStore);

    [HttpGet("Export")]
    public async Task<IActionResult> ExportAsync(ODataQueryOptions<Resource> options) => await _excelExportService.ExportAsync(await ExportAsync<ResourceExportModel>(options));

    /// <summary>
    /// 修改资源父级
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeParent")]
    public async Task<IActionResult> ChangeParentAsync(ChangeParentViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} parent to {parent}", _dataService.UserName, viewModel.Id, viewModel.ParentId);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource is null || viewModel.ParentId is null)
        {
            return NotFound();
        }

        try
        {
            await _resourceAccessStore.SetParentAsync(resource, viewModel.ParentId);
            await _dataService.UpdateAsync(resource);
            _logger.LogWarning("user {user} success to change the resource {resource} parent to {parent}", _dataService.UserName, resource.Name, viewModel.ParentId);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} parent to {parent} throw exception", _dataService.UserName, resource.Name, viewModel.ParentId);
        }

        return BadRequest($"修改资源 {resource.Name} 父级没有成功!");
    }
    /// <summary>
    /// 修改资源所有者
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeOwner")]
    public async Task<IActionResult> ChangeOwnerAsync(ChangeOwnerViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} owner to {owner} and owner type to {ownerType}", _dataService.UserName, viewModel.Id, viewModel.OwnerId, viewModel.IdentityType);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource is null || viewModel.OwnerId is null)
        {
            return NotFound();
        }
        try
        {
            await _resourceAccessStore.SetOwnerAsync(resource, viewModel.OwnerId);
            await _dataService.UpdateAsync(resource);
            _logger.LogWarning("user {user} success to change the resource {resource} owner to {owner} and owner type to {ownerType}", _dataService.UserName, resource.Name, viewModel.OwnerId, viewModel.IdentityType);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} owner to {owner} and owner type to {ownerType} throw exception", _dataService.UserName, resource.Name, viewModel.OwnerId, viewModel.IdentityType);
        }

        return BadRequest($"修改资源 {resource.Name} 所有者没有成功!");
    }
    /// <summary>
    /// 修改资源可访问级别
    /// </summary>
    /// <param name="viewModel"></param>
    /// <returns></returns>
    [HttpPost("ChangeLevel")]
    public async Task<IActionResult> ChangeLevelAsync(ResourceChangeLevelViewModel viewModel)
    {
        _logger.LogInformation("user {user} will change the resource {resource} level to {level} and access level to {accessLevel}", _dataService.UserName, viewModel.Id, viewModel.LevelName, viewModel.AccessLevel);
        var resource = await _dataService.GetAsync(viewModel.Id);
        if (resource is null || viewModel.LevelName is null)
        {
            return NotFound();
        }
        try
        {
            await _resourceAccessStore.SetLevelAsync(resource, viewModel.LevelName, CancellationToken);
            await _resourceAccessStore.SetAccessLevelAsync(resource, viewModel.AccessLevel, CancellationToken);
            await _dataService.UpdateAsync(resource);
            _logger.LogWarning("user {user} success to change the resource {resource} level to {level} and access level to {accessLevel}", _dataService.UserName, resource.Name, viewModel.LevelName, viewModel.AccessLevel);
            return Ok();
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "user {user} change the resource {resource} level to {level} and access level to {accessLevel} throw exception", _dataService.UserName, resource.Name, viewModel.LevelName, viewModel.AccessLevel);
        }

        return BadRequest($"修改资源 {resource.Name} 级别没有成功!");
    }
}